package cn.ren.cloud.service.impl;


import cn.ren.cloud.constants.VerifyCodeConstant;
import cn.ren.cloud.domain.MessageSms;
import cn.ren.cloud.dto.RedisSmsVerifyDto;
import cn.ren.cloud.dto.SmsSendDTO;
import cn.ren.cloud.enums.GlobelExceptionEnum;
import cn.ren.cloud.properties.VerifyCodeProperties;
import cn.ren.cloud.service.IMessageSmsService;
import cn.ren.cloud.service.IVerifyCodeService;
import cn.ren.cloud.utils.AssertUtil;
import cn.ren.cloud.utils.StrUtils;
import cn.ren.cloud.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author 23508
 */
@Slf4j
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {


    private final RedisTemplate<Object, Object> redisTemplate;
    private final IMessageSmsService messageSmsService;
    private final VerifyCodeProperties verifyCodeProperties;


    public VerifyCodeServiceImpl(RedisTemplate<Object, Object> redisTemplate, IMessageSmsService messageSmsService, VerifyCodeProperties verifyCodeProperties) {
        this.redisTemplate = redisTemplate;
        this.messageSmsService = messageSmsService;
        this.verifyCodeProperties = verifyCodeProperties;
    }


    /**
     * 获取图形验证码
     *
     * @param key 返回的值
     * @return base64Str
     */
    @Override
    public String getImageCode(String key) {
        // 判断key值是否为空
        AssertUtil.isNotNull(key, GlobelExceptionEnum.COMMON_REDIS_IS_NULL);
        // 新建时间
        Date date = new Date();
        //获取随机验证码
        String code = StrUtils.getComplexRandomString(verifyCodeProperties.getCodeSize());
        // 将图形验证码，创建时间，过期时间等存入Redis
        RedisSmsVerifyDto redisSmsVerifyDto = new RedisSmsVerifyDto(code, date.getTime());
        // 设置拼接图形验证码key值存入redis
        String redisCodeKey = VerifyCodeConstant.REDIS_PICTURE_CODE + key;
        // 设置过期时间
        Long overTime = verifyCodeProperties.getOverTime();
        redisTemplate.opsForValue().set(redisCodeKey, redisSmsVerifyDto, overTime, TimeUnit.MILLISECONDS);
        // 转换为base64字符返回前端
        String base64Str = VerifyCodeUtils.verifyCode(verifyCodeProperties.getCaptchaWide(), verifyCodeProperties.getCaptchaHigh(), code);
        return base64Str;
    }


    /**
     * 获取短信验证码
     *
     * @param dto dto
     */
    @Override
    public void sendSmsCode(SmsSendDTO dto) {
        // 判断电话是否为空:使用断言工具判断
        AssertUtil.isPhone(dto.getMobile(), GlobelExceptionEnum.COMMON_PHONE_ERROR);
        // 设置拼接手机验证码key值存入redis
        String redisCodeKey = VerifyCodeConstant.REDIS_REGISTER_PHONE + dto.getMobile();
        Object o = redisTemplate.opsForValue().get(redisCodeKey);
        String code = "";
        //新建一个当前时间
        Date date = new Date();
        // 判断短信验证码是否为空
        code = getSmsCode(date, o);
        // 将短信验证码，创建时间，过期时间等存入Redis
        RedisSmsVerifyDto redisSmsVerifyDto = new RedisSmsVerifyDto(code, date.getTime());
        Long overTime = verifyCodeProperties.getOverTime();
        redisTemplate.opsForValue().set(redisCodeKey, redisSmsVerifyDto, overTime, TimeUnit.MILLISECONDS);
        Long overTimeMinute = overTime / verifyCodeProperties.getMillisecondToMinute();
        String content = String.format(verifyCodeProperties.getContent(), code, overTimeMinute);
        // 保存短信日志
        saveMessageSms(date, content);
        // 打印日志
        log.info(content);
    }

    /**
     * 添加短信日志
     *
     * @param date 时间
     * @param content 内容
     */
    private void saveMessageSms(Date date, String content) {
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(verifyCodeProperties.getContent());
        String ip = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRemoteAddr();
        messageSms.setIp(ip);
        messageSms.setContent(content);
        messageSms.setSendTime(date);
        // 添加
        messageSmsService.insert(messageSms);
    }

    /**
     * 判断短信验证码是否为空
     *
     * @param date 时间
     * @param o redis内的值
     * @return code
     */
    private String getSmsCode(Date date, Object o) {
        String code;
        if (o == null) {
            // 为空，生成新验证码
            code = StrUtils.getRandomString(verifyCodeProperties.getCodeSize());
        } else {
            RedisSmsVerifyDto redisSmsVerifyDto = (RedisSmsVerifyDto) o;
            boolean boo = (date.getTime() - redisSmsVerifyDto.getTime()) >= verifyCodeProperties.getIntervalTime();
            // 不为空，判断时间是否大于等于1分钟
            AssertUtil.isTrue(boo, GlobelExceptionEnum.COMMON_REPEAT_OPERATION_ERROR);
            // 小于1分钟，设置给code
            code = redisSmsVerifyDto.getCode();
        }
        return code;
    }
}
